package com.jl.magic.montage.compose;

import com.jl.magic.color.RgbWeightedSimilarity;
import com.jl.magic.color.Similarity;
import com.jl.magic.enums.SyntheticStyleEnum;
import com.jl.magic.montage.config.SquareInlayConfig;
import com.jl.magic.montage.model.Inlay;
import com.jl.magic.montage.style.AbstractSyntheticStyle;
import com.jl.magic.montage.style.SquareSyntheticStyle;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author jiangli
 * @create 2020/7/14 4:24 下午
 */
public class SquareSynthesizer extends AbstractSynthesizer {

    @Override
    public BufferedImage compose() {

        long start = System.currentTimeMillis();
        Similarity labSimilarity = new RgbWeightedSimilarity();
        subImageList.forEach(input -> {
            int[] rgb = input.getRgb();
            inlayList.parallelStream().forEach(inlay -> {
                int[] inlayRgb = inlay.getRgb();
                double lab = labSimilarity.distance(rgb, inlayRgb);
                inlay.setDistance(lab);
            });
            inlayList.sort(Comparator.comparing(Inlay::getDistance));
            List<Integer> noList = inlayList.subList(0, 2).stream().map(Inlay::getNo).collect(Collectors.toList());
            input.setNears(noList);
        });
        long end = System.currentTimeMillis();
        System.out.println("子图求相近颜色镶嵌图片耗时：" + (end - start) + "ms");

        Map<Integer, Integer> times = new HashMap<>(inlayList.size());
        inlayList.forEach(input -> times.put(input.getNo(), 0));

        Map<Integer, Inlay> inlayMap = new HashMap<>(inlayList.size());
        inlayList.forEach(input -> inlayMap.put(input.getNo(), input));

        SquareInlayConfig config = (SquareInlayConfig) inlayConfig;
        SyntheticStyleEnum[] styleEnum = config.getSyntheticStyleEnum();
        AbstractSyntheticStyle syntheticStyle = new SquareSyntheticStyle();

        int minSide = config.getSide();
        int[] slice = config.getSlice();
        int targetWidth = slice[0] * minSide;
        int targetHeight = slice[1] * minSide;

        BufferedImage target = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_BGR);
        Graphics graphics = target.getGraphics();
        subImageList.parallelStream().forEach(input -> {
            long s = System.currentTimeMillis();
            int x = (input.getX() - 1) * minSide;
            int y = (input.getY() - 1) * minSide;
            List<Integer> nears = input.getNears();//主颜色相近的镶元图片编号
            Map<Integer, Integer> temp = new HashMap<>(11);
            nears.forEach(near -> temp.put(near, times.get(near)));
            List<Map.Entry<Integer, Integer>> entryList = new ArrayList<>(temp.entrySet());
            entryList.sort(Map.Entry.comparingByValue());
            int inlayNo = entryList.get(0).getKey();
            Inlay inlay = inlayMap.get(inlayNo);
            long s1 = System.currentTimeMillis();
            BufferedImage bufferedImage = inlay.getBufferedImage();
            long s2 = System.currentTimeMillis();
            bufferedImage = syntheticStyle.stylize(bufferedImage, styleEnum[0]);
            graphics.drawImage(bufferedImage, x, y, null);
            long s3 = System.currentTimeMillis();
            times.put(inlayNo, times.get(inlayNo) + 1);
            long s4 = System.currentTimeMillis();
            /*System.out.println("子图一次处理，获取近色图片耗时：" + (s1 - s) + "ms，近色图片像素转image耗时：" + (s2 - s1) +
                    "ms，镶图耗时：" + (s3 - s2) + "ms，其他耗时：" + (s4 - s3) + "ms");*/
        });
        graphics.dispose();

        subImageList.clear();

        long end2 = System.currentTimeMillis();
        System.out.println("合成图片耗时：" + (end2 - end) + "ms");

        return target;
    }

}
